package functional.methodreferences;

/**
 * @ClassName UnboundMethodReference
 * @PackageName functional
 * @projectName myThread
 * @Description 
 * @Author games
 * @Date 2025/8/26 上午10:50
 * @Version 1.0
 */
// 没有方法引用的对象

class X {
    String f() {
        return "X::f()";
    }
}

class X2 {
    String f2() {
        return "X::f()";
    }
}

interface MakeString {
    String make();
}

interface TransformX {
    String transform(X x);
}

/**
 * 未绑定的方法引用
 * 未绑定的方法引用是指没有关联对象的普通（非静态）方法。 使用未绑定的引用之前，我们必须先提供对象：
 */
public class UnboundMethodReference {
    public static void main(String[] args) {
         //MakeString ms = X::f; // [1]
        /**
         * 引用的具体方法不同：
         * TransformX sp = X::f：引用的是 X 类的 f() 方法
         * TransformX sp2 = X2::f2：引用的是 X2 类的 f2() 方法
         * 类型兼容性差异：
         * 两者都符合 TransformX 接口的签名要求：String transform(X x)
         * 但 X::f 可以直接匹配，因为参数类型就是 X
         * X2::f2 在编译时会报错，因为 X2 类型与 TransformX.transform(X x) 方法参数类型不匹配
         */
        TransformX sp = X::f;
        //TransformX sp2 = X2::f2;
        X x = new X();
        /**
         * 截止目前，我们已经知道了与接口方法同名的方法引用。 在 [1]，我们尝试把 X 的 f() 方法引用赋值给 MakeString。结果：即使 make() 与 f() 具有相同的签名，编译也会报“invalid method reference”（无效方法引用）错误。 这是因为实际上还有另一个隐藏的参数：我们的老朋友 this。 你不能在没有 X 对象的前提下调用 f()。 因此，X :: f 表示未绑定的方法引用，因为它尚未“绑定”到对象。
         *
         * 要解决这个问题，我们需要一个 X 对象，所以我们的接口实际上需要一个额外的参数，如上例中的 TransformX。 如果将 X :: f 赋值给 TransformX，在 Java 中是允许的。我们必须做第二个心理调整——使用未绑定的引用时，函数式方法的签名（接口中的单个方法）不再与方法引用的签名完全匹配。 原因是：你需要一个对象来调用方法。
         *
         * [2] 的结果有点像脑筋急转弯。我拿到未绑定的方法引用，并且调用它的transform()方法，将一个X类的对象传递给它，然后就以某种方式导致了对 x.f() 的调用。Java知道它必须拿到第一个参数，该参数实际就是this，并在其上调用方法。
         *
         * 如果你的函数式接口中的方法有多个参数，就以第一个参数接受this的模式来处理。
         */
        System.out.println(sp.transform(x)); // [2]
        System.out.println(x.f()); // 同等效果
    }



}
